<?php
/**
 * XuYuan Project
 *
 * @package	XueYuan 
 * @author	Jiuchi Team
 * @since	Version 1.0.0
 * @filesource
 */
defined('BASEPATH') OR exit('No direct script access allowed');
/**
 * Filter tools
 * @author Wayne Yu
 */
class Varfilter{
	/**
	 * 过滤内容
	 * @var unknown
	 */
	const FILTER_INT 		= 'int';
	const FILTER_BOOL 		= 'bool';
	const FILTER_FLOAT 		= 'float';
	const FILTER_REGEXP 	= 'regexp';
	const FILTER_URL 		= 'url';
	const FILTER_EMAIL 		= 'email';
	const FILTER_IP 		= 'ip';
	const FILTER_STRING 	= 'string';
	const FILTER_STRIPPED 	= 'stripped';
	const FILTER_ENCODE 	= 'encoded';
	const FILTER_CHARS 		= 'chars';
	const FILTER_SEMAL 		= 'semail';
	const FILTER_SURL 		= 'surl';
	const FILTER_SINT 		= 'sint';
	const FILTER_SFLOAT 	= 'sfloat';
	const FILTER_QUOTES 	= 'quotes';
	const FILTER_OCTAL 		= 'octal';
	const FILTER_HEX 		= 'hex';
	const FILTER_SLOW 		= 'slow';
	const FILTER_SHIGH 		= 'shigh';
	const FILTER_ELOW		= 'elow';
	const FILTER_EHIGH  	= 'ehigh';
	const FILTER_EAMP 		= 'eamp';
	const FILTER_NOQUOTES 	= 'noquotes';
	const FILTER_NULL 		= 'null';
	const FILTER_FRACTION 	= 'fraction';
	const FILTER_THOUSAND 	= 'thousand';
	const FILTER_SCIENTIFIC = 'scientific';
	const FILTER_SREQUIRED 	= 'srequired';
	const FILTER_IPV4 		= 'ipv4';
	const FILTER_IPV6		= 'ipv6';
	const FILTER_CALLBACK	= 'callback';
	const FILTER_ARRAY 		= 'array';
	
	
    private static $_options = array(
        self::FILTER_INT   		=> FILTER_VALIDATE_INT,//validate value as integer
        self::FILTER_BOOL  		=> FILTER_VALIDATE_BOOLEAN,//retrun true for "1","true","on","yes"
        self::FILTER_FLOAT 		=> FILTER_VALIDATE_FLOAT,//validate value as float
        self::FILTER_REGEXP		=> FILTER_VALIDATE_REGEXP,
        self::FILTER_URL   		=> FILTER_VALIDATE_URL,//validate value as url
        self::FILTER_EMAIL 		=> FILTER_VALIDATE_EMAIL,//validate value as e-mail
        self::FILTER_IP    		=> FILTER_VALIDATE_IP,//validate value as IP address
        self::FILTER_STRING  	=> FILTER_SANITIZE_STRING,
        self::FILTER_STRIPPED	=> FILTER_SANITIZE_STRIPPED,
        self::FILTER_ENCODE 	=> FILTER_SANITIZE_ENCODED,//URL-encode string,optionally strip or encode special characters
        self::FILTER_CHARS    	=> FILTER_SANITIZE_SPECIAL_CHARS,
        self::FILTER_SEMAL   	=> FILTER_SANITIZE_EMAIL,//remove all characters except letters,digits and !#$%&'*+-/=?^_`{|}~@.[]
        self::FILTER_SURL    	=> FILTER_SANITIZE_URL,
        self::FILTER_SINT     	=> FILTER_SANITIZE_NUMBER_INT,
        self::FILTER_SFLOAT   	=> FILTER_SANITIZE_NUMBER_FLOAT,//Remove all characters except digits,+- and optionally .eE
        self::FILTER_QUOTES  	=> FILTER_SANITIZE_MAGIC_QUOTES,//Apply addslashes()
        self::FILTER_OCTAL   	=> FILTER_FLAG_ALLOW_OCTAL,
        self::FILTER_HEX     	=> FILTER_FLAG_ALLOW_HEX,
        self::FILTER_SLOW    	=> FILTER_FLAG_STRIP_LOW,
        self::FILTER_SHIGH   	=> FILTER_FLAG_STRIP_HIGH,
        self::FILTER_ELOW    	=> FILTER_FLAG_ENCODE_LOW,
        self::FILTER_EHIGH   	=> FILTER_FLAG_ENCODE_HIGH,
        self::FILTER_EAMP    	=> FILTER_FLAG_ENCODE_AMP,
        self::FILTER_NOQUOTES	=> FILTER_FLAG_NO_ENCODE_QUOTES,
        self::FILTER_NULL    	=> FILTER_FLAG_EMPTY_STRING_NULL,
        self::FILTER_FRACTION	=> FILTER_FLAG_ALLOW_FRACTION,
        self::FILTER_THOUSAND	=> FILTER_FLAG_ALLOW_THOUSAND,
        self::FILTER_SCIENTIFIC	=> FILTER_FLAG_ALLOW_SCIENTIFIC,
        self::FILTER_SREQUIRED	=> FILTER_FLAG_SCHEME_REQUIRED,
        self::FILTER_IPV4    	=> FILTER_FLAG_IPV4,
        self::FILTER_IPV6    	=> FILTER_FLAG_IPV6,
        self::FILTER_CALLBACK 	=> FILTER_CALLBACK,
        self::FILTER_ARRAY   	=> FILTER_REQUIRE_ARRAY
    ); 

    private static $_data=array();
    private static $_flag=array();

    /**
     * 获取过滤数组值
     * @param unknown $key
     * @return multitype:string |NULL
     */
    public static function getOption($key){
        if(array_key_exists($key,self::$_options)){
        	return self::$_options[$key];
        }   
        return NULL;
    } 

    /**
     * getInt 验证$_GET变量是否是整数
     * e.g.
     * <code>
     * LFilter::getInt('id');
     * </code>
     *
     * @param string $field
     * @param int $min
     * @param int $max
     * @access public
     * @return bool
     */
    public static function getInt($int,$min=null,$max=null){
        if($min||$max){ 
        	self::$_data=array('min_range'=>$min,'max_range'=>$max);
        }
        return filter_input(INPUT_GET,$int,self::getOption('int'),self::$_data);
    } 

    /**
     * checkInt 检查$int变量是否是整数
     * e.g.
     * <code>
     *  LFilter::checkInt($_GET['id']);
     *  LFilter::checkInt($_GET['id'],20,2000);
     * </code>
     *
     * @param var $int
     * @param int $min
     * @param int $max
     * @static
     * @access public
     * @return bool
     */
    public static function checkInt($int,$min=null,$max=null){
        if($min||$max) {
        	self::$_data=array('min_range'=>$min,'max_range'=>$max);
        }
        return filter_var($int,self::getOption('int'),self::$_data);
    } 

    /**
     * postInt 检查$_POST变量是否是整数
     * <code>
     * LFilter::postInt('id');
     * </code>
     *
     * @param string $int
     * @param int $min
     * @param int $max
     * @static
     * @access public
     * @return bool
     */

    public static function postInt($int,$min=null,$max=null){
        if($min||$max) {
        	self::$_data=array('min_range'=>$min,'max_range'=>$max);
        }
        return filter_input(INPUT_POST,$int,self::getOption('int'),self::$_data);
    } 

    /**
     * getString 检查$_GET变量是否为字符串
     * <code>
     * LFilter::getString('name');
     * LFilter::getString('name','chars');
     * </code>
     *
     * @param mixed $str
     * @param string $type
     * @static
     * @access public
     * @return void
     */
    public static function getString($str,$type='string') {
        return filter_input(INPUT_GET,$str,self::getOption($type));
    } 

    /**
     * checkString 检测变量是否为字符串
     *
     * @param string $string
     * @param string $type
     * @param array $flag
     * @static
     * @access public
     * @return void
     */
    public static function checkString($string,$type='string',$flag=array()){
        return filter_var($string,self::getOption($type));
    }

    /**
     * postString 检测$_POST变量是否为字符串
     *
     * @param mixed $string
     * @param string $type
     * @param array $flag
     * @static
     * @access public
     * @return void
     */
    public static function postString($string,$type='string',$flag=array()) {
        return filter_input(INPUT_POST,$string,self::getOption($type));
    } 

    /**
     * postFloat 检测是否为浮点数
     * <code>
     * LFilter::postFloat('price');
     * </code>
     *
     * @param mixed $float
     * @param mixed $decimal
     * @param mixed $allow
     * @static
     * @access public
     * @return void
     */
    public static function postFloat($float,$decimal=null,$allow=true){
        if($decimal) {
        	self::$_data['options']['decimal']=$decimal;
        }
        self::$_data['flags']=self::getOption('thousand');
        return filter_input(INPUT_POST,$float,self::getOption('float'),self::$_data);
    } 
	
    /**
     * 获得浮点值
     * @param unknown $float
     * @param string $decimal
     * @param string $allow
     * @return mixed
     */
    public static function getFloat($float,$decimal=null,$allow=true){
        if($decimal) {
        	self::$_data['options']['decimal']=$decimal;
        }
        self::$_data['flags']=self::getOption('thousand');
        return filter_input(INPUT_GET,$float,self::getOption('float'),self::$_data);
    }

    /**
     * 检查浮点数值
     * @param unknown $float
     * @param string $decimal
     * @param string $allow
     * @return mixed
     */
    public static function checkFloat($float,$decimal=null,$allow=true){
        if($decimal){
        	self::$_data['options']['decimal']=$decimal;
        }
        self::$_data['flags']=self::getOption('thousand');
        return filter_var($float,self::getOption('float'),self::$_data);
    } 

    /**
     * 
     * @param unknown $email
     * @return mixed
     */
    public static function postEmail($email){
        return filter_input(INPUT_POST,$email,self::getOption('email'));
    }

    /**
     * 
     * @param unknown $email
     * @return mixed
     */
    public static function getEmail($email){
        return filter_input(INPUT_GET,$email,self::getOption('email'));
    } 

    /**
     * 
     * @param unknown $email
     * @return mixed
     */
    public static function checkEmail($email){
        return filter_var($email,self::getOption('email'));
    } 

    /**
     * 
     * @param unknown $url
     * @return mixed
     */
    public static function postUrl($url){
        return filter_input(INPUT_POST,$url,self::getOption('url'));
    } 

    /**
     * 
     * @param unknown $url
     * @return mixed
     */
    public static function getUrl($url){
        return filter_input(INPUT_GET,$url,self::getOption('url'));
    } 

    /**
     * 
     * @param unknown $url
     * @return mixed
     */
    public static function checkUrl($url){
        return filter_var($url,self::getOption('url'));
    } 

    /**
     * 
     * @param unknown $ip
     * @return mixed
     */
    public static function postIp($ip){
        return filter_input(INPUT_POST,$ip,self::getOption('ip'));

    } 

    /**
     * 
     * @param unknown $ip
     * @return mixed
     */
    public static function getIp($ip){
        return filter_input(INPUT_GET,$ip,self::getOption('ip'));
    } 

    /**
     * 
     * @param unknown $ip
     * @return mixed
     */
    public static function checkIp($ip){
        return filter_var($ip,self::getOption('ip'));
    }
    
    /**
     * postArray 对$_POST形式$args数组进行过滤,返回数组
     * eg:
     * <code>
     * $args = array(
     *      'productId' => 'int',
     *      'name'  => 'string',
     *      'tagId' => array('int','array'),
     *      'price' => array('float')
     *  );
     * LFilter::postArray($args);
     * </code>
     *
     * @param string $args
     * @access public
     * @return array
     */
    public function postArray($args,$type=false){
        if(empty($_POST)) {
        	return NULL;
        }
        return filter_input_array(INPUT_POST,self::getArrayArgs($args));
    }

    /**
     * 
     * @param unknown $args
     * @param string $type
     * @return NULL|mixed
     */
    public function getArray($args,$type=false) {
        if ( empty($_GET) ) {
        	return NULL;
        }        
        return filter_input_array(INPUT_GET,self::getArrayArgs($args));
    }

    /**
     * filterVarArray 对数据$data,以$args数组条件进行过滤,返回数组
     *
     * eg:
     * <code>
     * $data = array(
     *      'product_id'    => 'libgd<script>',
     *      'component'     => '10',
     *      'versions'      => '2.0.33',
     *      'testscalar'    => array('2', '23', '10', '12'),
     *      'testarray'     => '2',
     *  );
     * $args = array(
     *      'product_id'   => 'string',
     *      'component'    => array('int','',array('min_range' => 1, 'max_range' => 11)),
     *      'testscalar'   => array('int','array'),
     *      'testarray'    => array('int','array')
     *  );
     * LFilter::checkArray($data,$args);
     * </code>
     *
     * @param mixed $args
     * @access public
     * @return array
     */

    public function checkArray($data,$args,$type=false) {
        if(empty($data)) {
        	return NULL;
        }
        $defs = self::getArrayArgs($args,$type);
        return filter_var_array($data,$defs);
    } 

    /**
     * getArrayArgs  将过滤条件转换成filter函数处理的数组
     *
     * @param mixed $args
     * @access public
     * @return array
     */
    public static function getArrayArgs($args,$type=null) {
        $defs = array();
        foreach ($args as $key => $arg) {
            if(!is_array($arg)){
            	$arg = array($arg);
            }
            if(isset($arg[0])){
            	$defs[$key]['filter'] = self::getOption($arg[0]);
            }
            if(isset($arg[1])){
            	$defs[$key]['flags'] = self::getOption($arg[1]);
            }
            if(isset($arg[2])){
            	$defs[$key]['options'] = self::getOption($arg[2]);
            }
        }
        return $defs;
    }
    
    /**
     * 
     * @param unknown $data
     * @return mixed
     */
    public static function checkMobile($data){
    	return filter_var($data,FILTER_VALIDATE_REGEXP,array('options'=>array('regexp'=>'/^1\d{10}$/') ) );
    }
    
    /**
     * 
     * @param unknown $data
     * @return string
     */
    public static function filterHtml($data){
    	return strip_tags($data);
    }
    
    /**
     * 过滤js
     * @param unknown $data
     * @return mixed
     */
    public static function filterJs($data) {
    	return $data;
    	$data = self::delTag($data,'script');
		$data = preg_replace_callback('/<\s*([^\s>]+)\s+(.*?)\s*>/ims',
				function ($matches){
					$tag = $matches[1];
					$attrList = explode(' ',$matches[2]);
					foreach($attrList as $key=>$pair){
						list($attrName,$attrValue) = explode('=',$pair);
						if(strtolower(substr($attrName,0,2))=='on'){
							unset($attrList[$key]);
						}
					}
					$data = '<'.$tag.' '.implode(' ',$attrList).'>';
					return $data;
				}
				,$data);//删除html标签的on属性
		$data = preg_replace('/expression/ims','expresion',$data);//破坏掉css扩展
		$data = preg_replace('/expression_r/ims','expresion_r',$data);
		$data = preg_replace('/javascript\s*:/ims','javasscript:',$data);//破坏掉xss
		$data = preg_replace('/vbscript\s*:/ims','vbsscript:',$data);
		//检查第三方视频分享
		$data = preg_replace_callback('/<\s*embed\s+(.*?)\s*\/?\s*>/ims',
				function ($str){
					$attrList = explode(' ',$str[1]);
					if($attrList){
						foreach($attrList as $attr){
							if(empty($attr)) continue;
				
							list($attrName,$attrValue) = explode('=',$attr);
							$attrList2[strtolower($attrName)] = $attrValue;
						}
					}
				
					switch(strtolower($attrList2['type'])){
						case '"application/x-shockwave-flash"'://检查第三方视频分享
							$attrList2['type']			= '"application/x-shockwave-flash"';
							$attrList2['pluginspage']	= '"http://www.macromedia.com/go/getflashplayer"';
							$attrList2['src']			= '"'.self::checkShareVideo(trim($attrList2['src'],'"\'')).'"';
							break;
						default:
							return false;
							break;
					}				
					foreach($attrList2 as $key=>$value) $attrList2[$key] = $key.'='.$value;				
					$str = '<embed '.implode(' ',$attrList2).' />';				
					return $str;
				}
				,$data);//检查embed
		$data = self::delTag($data,'object');
		return $data;
    }
    
    /**
     * 
     * @param unknown $data
     * @return boolean|string
     */
    static private function checkEmbed($str){
    	$attrList = explode(' ',$str[1]);
    	if($attrList){
    		foreach($attrList as $attr){
    			if(empty($attr)) continue;
    
    			list($attrName,$attrValue) = explode('=',$attr);
    			$attrList2[strtolower($attrName)] = $attrValue;
    		}
    	}
    
    	switch(strtolower($attrList2['type'])){
    		case '"application/x-shockwave-flash"'://检查第三方视频分享
    			$attrList2['type']			= '"application/x-shockwave-flash"';
    			$attrList2['pluginspage']	= '"http://www.macromedia.com/go/getflashplayer"';
    			$attrList2['src']			= '"'.self::checkShareVideo(trim($attrList2['src'],'"\'')).'"';
    			break;
    		default:
    			return false;
    			break;
    	}
    
    	foreach($attrList2 as $key=>$value) $attrList2[$key] = $key.'='.$value;
    
    	$str = '<embed '.implode(' ',$attrList2).' />';
    
    	return $str;
    }
    
    /**
     * 
     * @param unknown $data
     * @return string|unknown
     */
    static private function checkShareVideo($data){
    	$host = parse_url($data,PHP_URL_HOST);
    	$domainList = explode('.',$host);
    	$domainList = array_slice($domainList,-2);
    	$host = implode('.',$domainList);
    
    	$videoHostList = array('youku.com','tudou.com','ku6.com','joy.cn','56.com');
    	if(!in_array($host,$videoHostList)) {
    		return '';//可修改为广告视频
    	}    
    	return $data;
    }
    
    /**
     * 删除html标签的on属性
     * Enter description here ...
     * @param array $matches
     */
    static private function delOn($matches){
    	$tag = $matches[1];
    	$attrList = explode(' ',$matches[2]);
    	foreach($attrList as $key=>$pair){
    		list($attrName,$attrValue) = explode('=',$pair);
    		if(strtolower(substr($attrName,0,2))=='on'){
    			unset($attrList[$key]);
    		}
    	}
    	$data = '<'.$tag.' '.implode(' ',$attrList).'>';
    	return $data;
    }
    
    static private function delTag($data,$tag){
    	$data = preg_replace('/<\s*'.$tag.'\s*[^>]*>.*?<\s*\/\s*'.$tag.'\s*[^>]*>/ims','',$data);
    	$data = preg_replace('/<\s*(\/\s*)?'.$tag.'\s*[^>]*(>)?/ims','',$data);
    	return $data;
    }
    
    /**
     * 单引号、双引号转为实体。数据须保真时，请使用mysql_real_escape_string。
     * @param unknown $data
     * @param string $flag
     */
    public static function filterSql($data, $flag = false){
    	if($flag == false){
    		return str_replace(array('"',"'","\0"),array('&#34;','&#39;',''),$data);
    	}else{
    		return mysql_real_escape_string($data);
    	}
    }
    
}

?>